/***************************************************************************
 *   Copyright (C) 2007 by Alexandre Masselot,,,   *
 *   alex@alex-laptop   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU Library General Public License as       *
 *   published by the Free Software Foundation; either version 2 of the    *
 *   License, or (at your option) any later version.                       *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this program; if not, write to the                 *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#ifndef BOLSPECTRUMLCMS_H
#define BOLSPECTRUMLCMS_H

#if defined(_MSC_VER) && !defined(isnan)
#include <float.h>
#define isnan(f) _isnan(f)
#endif

#ifdef HAVE_BOOST_SERIALIZATION
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/export.hpp>
#include <boost/serialization/utility.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/base_object.hpp>
#else
#endif

#ifdef HAVE_PROTOBUF
#ifdef _MSC_VER
// we don't create DLLs and thus don't need to pay attention to this warning
#pragma warning( disable: 4251 )
#endif
#include "runlcmsms.pb.h"
#endif

#include "spectrum.h"
#include "peakintensity.h"
namespace bol {
  
/**
  mslevel=1 peak collection.
  a description + retention time info
  and a collection of peak m/z, intensitiy and charges

  @author Alexandre Masselot,GeneBio,http://www.genebio.com, <alexandre.masselot@gmail.com>
 */
  class SpectrumLcms: public Spectrum<PeakIntensity*>{
    private:
      string m_description;
      const double m_retentionTime;

#ifdef HAVE_BOOST_SERIALIZATION
      // *** BOOST serialisation code ***
      friend class boost::serialization::access; // gives access to serialisator
      template<class Archive> void serialize ( Archive & ar, const unsigned int version ) const
      {
        // base class serialisation - warning, as there are several variable, the order is critical...
        // ... well not for XML. But for most other archive types.

        ar & boost::serialization::make_nvp("Description", m_description);
        ar & boost::serialization::make_nvp("retentionTime", m_retentionTime);

        // the peaks
        ar & boost::serialization::make_nvp("Spectrum", boost::serialization::base_object<Spectrum<PeakIntensity*> > ( *this ));
      }
#endif

    public:
      SpectrumLcms(const double rt):m_retentionTime(rt) {
      }

      ~SpectrumLcms();

      double retentionTime() const {
        return m_retentionTime;
      }

      void setDescription(const string& theValue) {
        m_description = theValue;
      }
      string description() const {
        return m_description;
      }

  };

#ifdef HAVE_PROTOBUF
/*  static inline void operator<< (protobuf::runlcmsms::Spectrum& pb, const class SpectrumLcms& s) {
    pb.set_description(s.description());
    pb.set_retentiontime(s.retentionTime());
    (void) (pb << static_cast< Spectrum<PeakIntensity*> > (s));
  }
*/
  namespace pb_common {
    static inline bool save(protobuf::RunLcmsms::Spectrum& pb, const class SpectrumLcms& s) {
      pb.set_description(s.description());
      if ((! isnan(s.retentionTime())) && s.retentionTime() >= 0.)
        pb.set_retentiontime(s.retentionTime());
      if (s.refid() >= 0)
        pb.set_refid(s.refid());
      return true;
    }
  }
  
  static inline bool protobufwithmap (protobuf::RunLcmsms::Spectrum& pb, const class SpectrumLcms& s, Ptr2IndexMapPtr spidx) {
    pb_common::save(pb, s);
    protobufwithmap(pb, static_cast< Spectrum<PeakIntensity*> > (s), spidx);
    return true;
  }

  static inline bool operator<< (protobuf::RunLcmsms::Spectrum& pb, const class SpectrumLcms& s) {
    pb_common::save(pb, s);
    pb << static_cast< Spectrum<PeakIntensity*> > (s);
    return true;
  }

  static inline bool operator>> (const protobuf::RunLcmsms::Spectrum& pb, class SpectrumLcms& s) {
    if (pb.has_description())
      s.setDescription(pb.description());
    if (pb.has_refid())
      s.setRefid(pb.refid());
    // retentiontime is set by the constructor when allocating new spectrum
    pb >> static_cast< Spectrum<PeakIntensity*> & > (s);
    true;
  }

#endif

}

#if defined(WIN32) && !defined(isnan)
#include<float.h>
#define isnan(f) _isnan(f)
#endif

#ifdef HAVE_BOOST_SERIALIZATION
#if defined(WIN32) && (BOOST_VERSION < 103600)
// other wise Visual Studio spits error messages
#include <boost/serialization/extended_type_info_typeid.hpp>
#endif
BOOST_CLASS_EXPORT_GUID(bol::SpectrumLcms, "SpectrumLcms") // register GUID
#endif

#endif
